package cn.itcast.n8;

import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author: AirMan
 * @date: 2025/4/23 21:14
 * @description:
 */
public class MyTestGenericDao {

    public static void main(String[] args) {
        GenericDao dao = new GenericDaoCached();
        System.out.println("============> 查询");
        String sql = "select * from emp where empno = ?";
        int empno = 7369;
        Emp emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);
        emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);
        emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);

        System.out.println("============> 更新");
        dao.update("update emp set sal = ? where empno = ?", 800, empno);
        emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);
    }
}


class MyGenericDaoCached extends GenericDao {

    private GenericDao dao = new GenericDaoCached();
    private Map<SqlPair, Object> cacheMap = new HashMap<>();

    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    @Override
    public <T> List<T> queryList(Class<T> beanClass, String sql, Object... args) {
        return super.queryList(beanClass, sql, args);
    }

    @Override
    public <T> T queryOne(Class<T> beanClass, String sql, Object... args) {
        // 1.查询缓存
        SqlPair key = new SqlPair(sql, args);

        rwl.readLock().lock(); // 读锁
        try {
            T value = (T) cacheMap.get(key);
            if (value != null) {
                return value;
            }
        } finally {
            rwl.readLock().unlock();
        }

        rwl.writeLock().lock(); // 写锁
        try {
            // double check
            T value = (T) cacheMap.get(key);
            if (value == null) {
                // 2.缓存没有，查询数据库
                value = super.queryOne(beanClass, sql, args);
                // 3.讲查询的数据放入缓存中
                cacheMap.put(key, value);
            }
            return value;
        } finally {
            rwl.writeLock().unlock();
        }
    }

    @Override
    public int update(String sql, Object... args) {
        rwl.writeLock().lock();
        try {
            // 更新数据库
            int update = super.update(sql, args);
            // 清除缓存
            cacheMap.clear();
            return update;
        } finally {
            rwl.writeLock().unlock();
        }
    }


    class SqlPair {
        private String sql;
        private Object[] args;

        public SqlPair(String sql, Object[] args) {
            this.sql = sql;
            this.args = args;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            SqlPair sqlPair = (SqlPair) o;
            return Objects.equals(sql, sqlPair.sql) && Objects.deepEquals(args, sqlPair.args);
        }

        @Override
        public int hashCode() {
            return Objects.hash(sql, Arrays.hashCode(args));
        }
    }
}